//
//  QRCode.swift
//  JKTools
//
//  Created by 姜奎 on 2024/4/24.
//

import Cocoa


class QRCode {
    static func toQRCode(_ inputMessage:String, size: CGSize) -> NSImage? {
        let ciImage = CIImage.toQRCode(inputMessage, size: size)
        let cgImage = ciImage?.toCGImage()
        let nsImage = cgImage?.toNSImage()
        return nsImage
    }
    
    static func toString(_ inputImage:NSImage) -> String? {
        let cgImage = inputImage.toCGImage()
        let ciImage = cgImage?.toCIImage()
        let string = ciImage?.toString()
        return string
    }
}

extension CIImage {
    
    static func toQRCode(_ inputMessage:String, size: CGSize) -> CIImage? {
        guard let filter = CIFilter(name: "CIQRCodeGenerator") else { return nil }
        filter.setDefaults()
        filter.setValue(inputMessage.data(using: .ascii), forKey: "inputMessage")
        /*
         "L", "M", "Q" 或 "H"。"L" 表示 7% 的代码字可以被修正。"M" 表示 15% 的代码字可以被修正。"Q" 表示 25% 的代码字可以被修正。"H" 表示 30% 的代码字可以被修正。这个参数是可选的，如果没有提供，那么将会使用默认级别 "M"
         */
        filter.setValue("L", forKey: "inputCorrectionLevel")
        //https://www.qrcode.com/en/about/error_correction.html
        guard  let outputImage = filter.outputImage else { return nil }
        let scaledOutput = outputImage.transformed(by: CGAffineTransform(scaleX: size.width / outputImage.extent.size.width,
                                                                              y: size.height / outputImage.extent.size.height))
        return scaledOutput
    }
    
    func update(tintColor: CIColor, backgroundColor: CIColor) -> CIImage? {
        guard let colorFilter = CIFilter(name: "CIFalseColor") else { return nil }
                
        colorFilter.setValue(self, forKey: kCIInputImageKey)
        colorFilter.setValue(tintColor, forKey: "inputColor0")
        colorFilter.setValue(backgroundColor, forKey: "inputColor1")
        return colorFilter.outputImage
    }

    // 添加logo需要评估 纠错百分比：inputCorrectionLevel
    func addLogo(image: CIImage, logo: CIImage) -> CIImage? {
            
        guard let combinedFilter = CIFilter(name: "CISourceOverCompositing") else { return nil }
        
        let centerTransform = CGAffineTransform(translationX: image.extent.midX - (logo.extent.size.width / 2), y: image.extent.midY - (logo.extent.size.height / 2))
        
        combinedFilter.setValue(logo.transformed(by: centerTransform), forKey: "inputImage")
        combinedFilter.setValue(image, forKey: "inputBackgroundImage")
        return combinedFilter.outputImage
    }
    
    func toCGImage() -> CGImage? {
        let context = CIContext()
        guard let cgImage = context.createCGImage(self, from: self.extent) else {
            return nil
        }
        return cgImage
    }
    
    func toString() -> String? {
        guard let detector = CIDetector(ofType: CIDetectorTypeQRCode, context: nil, options: nil) else { return nil }

        let features = detector.features(in: self)
        guard let qrFeature = features.first as? CIQRCodeFeature else { return nil }

        return qrFeature.messageString
    }
}

extension CGImage {
    func toNSImage() -> NSImage {
        let nsImage = NSImage(cgImage: self, size: NSSize(width: self.width, height: self.height))
        return nsImage
    }
    
    func toCIImage() -> CIImage {
        let ciImage = CIImage(cgImage: self)
        return ciImage
    }
}

extension NSImage {
    func toCGImage() -> CGImage? {
        let cgImage = self.cgImage(forProposedRect: &self.alignmentRect, context: nil, hints: nil)
        return cgImage
    }
}
